{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PEFT 进阶操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 自定义模型适配"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\Miniconda\\envs\\geo\\lib\\site-packages\\numpy\\_distributor_init.py:30: UserWarning: loaded more than 1 DLL from .libs:\n",
      "d:\\Miniconda\\envs\\geo\\lib\\site-packages\\numpy\\.libs\\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll\n",
      "d:\\Miniconda\\envs\\geo\\lib\\site-packages\\numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll\n",
      "  warnings.warn(\"loaded more than 1 DLL from .libs:\"\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from peft import LoraConfig, get_peft_model, PeftModel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Linear(in_features=10, out_features=10, bias=True)\n",
       "  (1): ReLU()\n",
       "  (2): Linear(in_features=10, out_features=2, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net1 = nn.Sequential(\n",
    "    nn.Linear(10, 10),\n",
    "    nn.ReLU(),\n",
    "    nn.Linear(10, 2)\n",
    ")\n",
    "net1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.weight torch.Size([10, 10])\n",
      "0.bias torch.Size([10])\n",
      "2.weight torch.Size([2, 10])\n",
      "2.bias torch.Size([2])\n"
     ]
    }
   ],
   "source": [
    "for name, param in net1.named_parameters():\n",
    "    print(name,param.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = LoraConfig(target_modules=[\"0\"],r=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Could not find the bitsandbytes CUDA binary at WindowsPath('d:/Miniconda/envs/geo/lib/site-packages/bitsandbytes/libbitsandbytes_cuda116.dll')\n",
      "The installed version of bitsandbytes was compiled without GPU support. 8-bit optimizers, 8-bit multiplication, and GPU quantization are unavailable.\n"
     ]
    }
   ],
   "source": [
    "model1 = get_peft_model(net1, config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PeftModel(\n",
       "  (base_model): LoraModel(\n",
       "    (model): Sequential(\n",
       "      (0): lora.Linear(\n",
       "        (base_layer): Linear(in_features=10, out_features=10, bias=True)\n",
       "        (lora_dropout): ModuleDict(\n",
       "          (default): Identity()\n",
       "        )\n",
       "        (lora_A): ModuleDict(\n",
       "          (default): Linear(in_features=10, out_features=4, bias=False)\n",
       "        )\n",
       "        (lora_B): ModuleDict(\n",
       "          (default): Linear(in_features=4, out_features=10, bias=False)\n",
       "        )\n",
       "        (lora_embedding_A): ParameterDict()\n",
       "        (lora_embedding_B): ParameterDict()\n",
       "        (lora_magnitude_vector): ModuleDict()\n",
       "      )\n",
       "      (1): ReLU()\n",
       "      (2): Linear(in_features=10, out_features=2, bias=True)\n",
       "    )\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "base_model.model.0.base_layer.weight torch.Size([10, 10])\n",
      "base_model.model.0.base_layer.bias torch.Size([10])\n",
      "base_model.model.0.lora_A.default.weight torch.Size([4, 10])\n",
      "base_model.model.0.lora_B.default.weight torch.Size([10, 4])\n",
      "base_model.model.2.weight torch.Size([2, 10])\n",
      "base_model.model.2.bias torch.Size([2])\n"
     ]
    }
   ],
   "source": [
    "for name, param in model1.named_parameters():\n",
    "    if name == 'base_model.model.0.base_layer.weight':\n",
    "        param1 = param\n",
    "    if name == 'base_model.model.0.base_layer.bias':\n",
    "        param2 = param\n",
    "    if name == 'base_model.model.0.lora_A.default.weight':\n",
    "        param3 = param\n",
    "    if name == 'base_model.model.0.lora_B.default.weight':\n",
    "        param4 = param\n",
    "    print(name,param.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 多适配器加载与切换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Linear(in_features=10, out_features=10, bias=True)\n",
       "  (1): ReLU()\n",
       "  (2): Linear(in_features=10, out_features=2, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net2 = nn.Sequential(\n",
    "    nn.Linear(10, 10),\n",
    "    nn.ReLU(),\n",
    "    nn.Linear(10, 2)\n",
    ")\n",
    "net2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "config1 = LoraConfig(target_modules=[\"0\"])\n",
    "model2 = get_peft_model(net2, config1)\n",
    "model2.save_pretrained(\"./loraA\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "config2 = LoraConfig(target_modules=[\"2\"])\n",
    "model2 = get_peft_model(net2, config2)\n",
    "model2.save_pretrained(\"./loraB\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Linear(in_features=10, out_features=10, bias=True)\n",
       "  (1): ReLU()\n",
       "  (2): Linear(in_features=10, out_features=2, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net2 = nn.Sequential(\n",
    "    nn.Linear(10, 10),\n",
    "    nn.ReLU(),\n",
    "    nn.Linear(10, 2)\n",
    ")\n",
    "net2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PeftModel(\n",
       "  (base_model): LoraModel(\n",
       "    (model): Sequential(\n",
       "      (0): lora.Linear(\n",
       "        (base_layer): Linear(in_features=10, out_features=10, bias=True)\n",
       "        (lora_dropout): ModuleDict(\n",
       "          (lora1): Identity()\n",
       "        )\n",
       "        (lora_A): ModuleDict(\n",
       "          (lora1): Linear(in_features=10, out_features=8, bias=False)\n",
       "        )\n",
       "        (lora_B): ModuleDict(\n",
       "          (lora1): Linear(in_features=8, out_features=10, bias=False)\n",
       "        )\n",
       "        (lora_embedding_A): ParameterDict()\n",
       "        (lora_embedding_B): ParameterDict()\n",
       "        (lora_magnitude_vector): ModuleDict()\n",
       "      )\n",
       "      (1): ReLU()\n",
       "      (2): Linear(in_features=10, out_features=2, bias=True)\n",
       "    )\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2 = PeftModel.from_pretrained(net2, model_id=\"./loraA/\", adapter_name=\"lora1\")\n",
    "model2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PeftModel(\n",
       "  (base_model): LoraModel(\n",
       "    (model): Sequential(\n",
       "      (0): lora.Linear(\n",
       "        (base_layer): Linear(in_features=10, out_features=10, bias=True)\n",
       "        (lora_dropout): ModuleDict(\n",
       "          (lora1): Identity()\n",
       "        )\n",
       "        (lora_A): ModuleDict(\n",
       "          (lora1): Linear(in_features=10, out_features=8, bias=False)\n",
       "        )\n",
       "        (lora_B): ModuleDict(\n",
       "          (lora1): Linear(in_features=8, out_features=10, bias=False)\n",
       "        )\n",
       "        (lora_embedding_A): ParameterDict()\n",
       "        (lora_embedding_B): ParameterDict()\n",
       "        (lora_magnitude_vector): ModuleDict()\n",
       "      )\n",
       "      (1): ReLU()\n",
       "      (2): lora.Linear(\n",
       "        (base_layer): Linear(in_features=10, out_features=2, bias=True)\n",
       "        (lora_dropout): ModuleDict(\n",
       "          (lora2): Identity()\n",
       "        )\n",
       "        (lora_A): ModuleDict(\n",
       "          (lora2): Linear(in_features=10, out_features=8, bias=False)\n",
       "        )\n",
       "        (lora_B): ModuleDict(\n",
       "          (lora2): Linear(in_features=8, out_features=2, bias=False)\n",
       "        )\n",
       "        (lora_embedding_A): ParameterDict()\n",
       "        (lora_embedding_B): ParameterDict()\n",
       "        (lora_magnitude_vector): ModuleDict()\n",
       "      )\n",
       "    )\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 加载适配器，在主模型已经加载的情况下采用 load_adapter 方法\n",
    "model2.load_adapter(\"./loraB/\", adapter_name=\"lora2\")\n",
    "model2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'lora1'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2.active_adapter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.9388, -0.9118]], grad_fn=<AddmmBackward0>)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2(torch.arange(0, 10).view(1, 10).float())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "base_model.model.0.base_layer.weight Parameter containing:\n",
      "tensor([[-1.4085e-01,  2.0996e-01, -1.6466e-01,  2.2782e-01,  2.2411e-01,\n",
      "         -2.7587e-01,  1.3421e-01,  1.0487e-01, -1.0017e-01,  2.0808e-01],\n",
      "        [ 1.3345e-01, -2.8845e-01,  1.3993e-01, -4.4553e-02, -2.6681e-01,\n",
      "         -3.0753e-01, -1.4108e-01,  2.8118e-01,  2.8712e-01,  8.7099e-02],\n",
      "        [ 2.9969e-01,  2.9739e-01, -2.4302e-01, -4.3835e-02, -6.8973e-02,\n",
      "          1.5273e-01, -1.7740e-01, -1.5906e-01, -1.4516e-02,  2.0751e-01],\n",
      "        [ 2.9650e-01,  2.9598e-01, -2.3326e-01,  2.9858e-01,  8.4589e-02,\n",
      "         -1.8566e-01, -1.2970e-01,  1.9112e-01,  9.7641e-02,  2.8968e-03],\n",
      "        [-1.0791e-01, -1.2451e-04,  9.1227e-02, -1.2749e-01, -3.5409e-02,\n",
      "          1.3501e-01, -1.4132e-01,  2.1643e-01,  1.7950e-01, -2.7317e-01],\n",
      "        [-1.8920e-01,  2.6021e-01, -1.3925e-01,  2.2595e-01, -1.0284e-01,\n",
      "         -2.8517e-01,  2.0683e-01,  1.2010e-01, -8.6377e-03,  1.8101e-01],\n",
      "        [ 2.9360e-01,  2.1962e-01, -2.6775e-01,  1.1998e-01, -2.6099e-01,\n",
      "          1.3167e-01,  1.7206e-01,  1.4280e-01,  2.3282e-01, -8.8005e-02],\n",
      "        [ 2.7409e-01, -5.6231e-02,  1.4593e-01,  2.7435e-01, -2.2451e-02,\n",
      "          2.0543e-01,  1.6230e-01,  1.9244e-01,  1.5682e-01, -1.5895e-01],\n",
      "        [-3.1073e-02,  1.0936e-01,  1.8510e-03, -3.6089e-02, -8.4059e-02,\n",
      "          4.3922e-02, -2.5310e-01, -2.0951e-01, -2.4317e-01, -3.1281e-01],\n",
      "        [ 9.5613e-02, -2.1377e-01, -1.7956e-01, -2.4156e-01,  2.5441e-01,\n",
      "          1.0501e-01,  4.7383e-04, -3.6489e-02, -4.0735e-02, -2.7525e-02]])\n",
      "base_model.model.0.base_layer.bias Parameter containing:\n",
      "tensor([ 0.2597,  0.3147, -0.0763, -0.1441, -0.1093, -0.0673,  0.2544,  0.1926,\n",
      "        -0.3069, -0.2526])\n",
      "base_model.model.0.lora_A.lora1.weight Parameter containing:\n",
      "tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], requires_grad=True)\n",
      "base_model.model.0.lora_B.lora1.weight Parameter containing:\n",
      "tensor([[1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1., 1., 1., 1., 1.]], requires_grad=True)\n",
      "base_model.model.2.base_layer.weight Parameter containing:\n",
      "tensor([[ 0.2894,  0.0351,  0.1765, -0.1614, -0.0605, -0.1286,  0.2772, -0.0686,\n",
      "          0.2999, -0.2506],\n",
      "        [-0.3073, -0.2905, -0.0874,  0.1060, -0.2261,  0.1938, -0.2373,  0.0954,\n",
      "          0.1640,  0.2748]])\n",
      "base_model.model.2.base_layer.bias Parameter containing:\n",
      "tensor([0.0111, 0.2031])\n",
      "base_model.model.2.lora_A.lora2.weight Parameter containing:\n",
      "tensor([[ 0.1412, -0.1835,  0.0540, -0.2503, -0.1811,  0.2322, -0.1376, -0.2623,\n",
      "         -0.0433, -0.2362],\n",
      "        [ 0.0391,  0.0332, -0.1680, -0.1073,  0.2151, -0.3057, -0.2457,  0.2977,\n",
      "          0.2013, -0.2702],\n",
      "        [ 0.1094, -0.0432, -0.1474,  0.2362, -0.0922,  0.1136, -0.2891, -0.1638,\n",
      "         -0.1970,  0.2411],\n",
      "        [ 0.0883,  0.2992, -0.1042,  0.3089, -0.2115, -0.1290,  0.2829,  0.1481,\n",
      "          0.2978,  0.2490],\n",
      "        [-0.1891, -0.2319,  0.2006,  0.0004, -0.1136,  0.2388,  0.0547, -0.0629,\n",
      "         -0.1512,  0.1248],\n",
      "        [-0.0718,  0.1120,  0.0990, -0.3149,  0.0418, -0.3043,  0.1701, -0.2600,\n",
      "         -0.1576,  0.1503],\n",
      "        [-0.2797,  0.0422, -0.0640,  0.2663, -0.0950, -0.1991, -0.0891, -0.0505,\n",
      "          0.0124,  0.0366],\n",
      "        [-0.1359, -0.1031, -0.0421,  0.2847,  0.0156, -0.2202,  0.2229, -0.0448,\n",
      "         -0.0707, -0.0231]])\n",
      "base_model.model.2.lora_B.lora2.weight Parameter containing:\n",
      "tensor([[0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0.]])\n"
     ]
    }
   ],
   "source": [
    "# 对权重进行更新\n",
    "for name, param in model2.named_parameters():\n",
    "    print(name, param)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "for name, param in model2.named_parameters():\n",
    "    if name in [\"base_model.model.0.lora_A.lora1.weight\", \"base_model.model.0.lora_B.lora1.weight\"]:\n",
    "        param.data = torch.ones_like(param)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 145.7027, -115.7137]], grad_fn=<AddmmBackward0>)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2(torch.arange(0, 10).view(1, 10).float())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "model2.set_adapter(\"lora2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'lora2'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2.active_adapter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.9388, -0.9118]], grad_fn=<AddBackward0>)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2(torch.arange(0, 10).view(1, 10).float())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 禁用适配器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "model2.set_adapter(\"lora1\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 145.7027, -115.7137]], grad_fn=<AddmmBackward0>)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model2(torch.arange(0, 10).view(1, 10).float())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.9388, -0.9118]])\n"
     ]
    }
   ],
   "source": [
    "with model2.disable_adapter():\n",
    "    print(model2(torch.arange(0, 10).view(1, 10).float()))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "transformers",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
